package com.haoxuer.discover.common.utils;

import static org.springframework.web.servlet.view.AbstractTemplateView.SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE;


import freemarker.core.Environment;
import freemarker.template.AdapterTemplateModel;
import freemarker.template.TemplateDateModel;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
import freemarker.template.TemplateNumberModel;
import freemarker.template.TemplateScalarModel;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.servlet.support.RequestContext;

/**
 * Freemarker标签工具类
 */
public abstract class DirectiveUtils {
  /**
   * 输出参数：对象数据
   */
  public static final String OUT_BEAN = "tag_bean";
  /**
   * 输出参数：列表数据
   */
  public static final String OUT_LIST = "tag_list";
  /**
   * 输出参数：分页数据
   */
  public static final String OUT_PAGINATION = "tag_pagination";
  /**
   * 参数：是否调用模板。
   */
  public static final String PARAM_TPL = "tpl";
  /**
   * 参数：次级模板名称
   */
  public static final String PARAM_TPL_SUB = "tplSub";

  /**
   * 将params的值复制到variable中
   *
   * @param env
   * @param params
   * @return 原Variable中的值
   * @throws TemplateException
   */
  public static Map<String, TemplateModel> addParamsToVariable(
      Environment env, Map<String, TemplateModel> params)
      throws TemplateException {
    Map<String, TemplateModel> origMap = new HashMap<String, TemplateModel>();
    if (params.size() <= 0) {
      return origMap;
    }
    Set<Map.Entry<String, TemplateModel>> entrySet = params.entrySet();
    String key;
    TemplateModel value;
    for (Map.Entry<String, TemplateModel> entry : entrySet) {
      key = entry.getKey();
      value = env.getVariable(key);
      if (value != null) {
        origMap.put(key, value);
      }
      env.setVariable(key, entry.getValue());
    }
    return origMap;
  }

  /**
   * 将variable中的params值移除
   *
   * @param env
   * @param params
   * @param origMap
   * @throws TemplateException
   */
  public static void removeParamsFromVariable(Environment env,
                                              Map<String, TemplateModel> params,
                                              Map<String, TemplateModel> origMap) throws TemplateException {
    if (params.size() <= 0) {
      return;
    }
    for (String key : params.keySet()) {
      env.setVariable(key, origMap.get(key));
    }
  }

  /**
   * 获得RequestContext
   * <p>
   * ViewResolver中的exposeSpringMacroHelpers必须为true
   *
   * @param env
   * @return
   * @throws TemplateException
   */
  public static RequestContext getContext(Environment env)
      throws TemplateException {
    TemplateModel ctx = env
        .getGlobalVariable(SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE);
    if (ctx instanceof AdapterTemplateModel) {
      return (RequestContext) ((AdapterTemplateModel) ctx)
          .getAdaptedObject(RequestContext.class);
    } else {
      throw new TemplateModelException("RequestContext '"
          + SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE
          + "' not found in DataModel.");
    }
  }


  /**
   * 模板调用类型
   */
  public enum InvokeType {
    body, custom, sysDefined, userDefined
  }

  public static Integer getInt(String name, Map<String, TemplateModel> params)
      throws TemplateException {
    TemplateModel model = params.get(name);
    if (model == null) {
      return null;
    }
    if (model instanceof TemplateScalarModel) {
      String s = ((TemplateScalarModel) model).getAsString();
      if (StringUtils.isBlank(s)) {
        return null;
      }
      try {
        return Integer.parseInt(s);
      } catch (NumberFormatException e) {
      }
    } else if (model instanceof TemplateNumberModel) {
      return ((TemplateNumberModel) model).getAsNumber().intValue();
    } else {
    }
    return 0;
  }

  public static String getString(String name,
                                 Map<String, TemplateModel> params) throws TemplateException {
    TemplateModel model = params.get(name);
    if (model == null) {
      return null;
    }
    if (model instanceof TemplateScalarModel) {
      return ((TemplateScalarModel) model).getAsString();
    } else if ((model instanceof TemplateNumberModel)) {
      return ((TemplateNumberModel) model).getAsNumber().toString();
    } else {
      return "";
    }
  }

  public static Date getDate(String name,
                             Map<String, TemplateModel> params) throws TemplateException {
    TemplateModel model = params.get(name);
    if (model == null) {
      return null;
    }
    if (model instanceof TemplateDateModel) {
      return ((TemplateDateModel) model).getAsDate();
    } else {
      return null;
    }
  }

  public static Long getLong(String name, Map<String, TemplateModel> params)
      throws TemplateException {
    TemplateModel model = params.get(name);
    if (model == null) {
      return null;
    }
    if (model instanceof TemplateScalarModel) {
      String s = ((TemplateScalarModel) model).getAsString();
      if (StringUtils.isBlank(s)) {
        return null;
      }
      try {
        return Long.parseLong(s);
      } catch (NumberFormatException e) {
      }
    } else if (model instanceof TemplateNumberModel) {
      return ((TemplateNumberModel) model).getAsNumber().longValue();
    } else {
    }
    return 0L;
  }

}
